package com.hk.hkvedio.controller;

import com.hk.hkvedio.config.HKConfig;
import com.hk.hkvedio.monitor.HkVideoMonitor;
import com.hk.hkvedio.service.IHkVideoService;
import com.hk.hkvedio.utils.HCNetSDK;
import com.hk.hkvedio.vo.FileInfoVo;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Timer;


@RestController
@RequestMapping(value = "hk")
public class HkVideoDownloadController {

    private Logger logger = LoggerFactory.getLogger(HkVideoDownloadController.class);

    @Autowired
    private IHkVideoService hkVideoService;

    private NativeLong nlUserID;

    private HCNetSDK hkSdk;
    private Timer timer;//下载用定时器

    private NativeLong m_lDownloadHandle = new NativeLong(-1);//download handle

    //回调信息
    private HkVideoMonitor hkVideoMonitor;
    //监听
    private NativeLong lListenHandle;
    //布防
    private NativeLong alarmChan;

    /**
     * 初始化和注册
     */
    public void init() {
        if (Objects.equals(hkSdk, null)) {
            hkSdk = hkVideoService.net_dvr_init();
        }
        if (Objects.equals(nlUserID, null)) {
            nlUserID = hkVideoService.net_dvr_login_v40();
        }
    }

    /**
     * 文件下载
     *
     * @return
     */
    @GetMapping(value = "/download")
    public String download() {
        try {
            init();
            if (m_lDownloadHandle.intValue() == -1) {
                HCNetSDK.NET_DVR_TIME startTime = new HCNetSDK.NET_DVR_TIME();
                HCNetSDK.NET_DVR_TIME endTime = new HCNetSDK.NET_DVR_TIME();

                //获取昨天的时间
                LocalDateTime localDateTime = LocalDateTime.now();
                localDateTime = localDateTime.plusDays(-1);
                int year = localDateTime.getYear();
                int month = localDateTime.getMonthValue();
                int day = localDateTime.getDayOfMonth();
                logger.info("年：{}", year);
                logger.info("月：{}", month);
                logger.info("日：{}", day);

                //开始时间
                startTime.dwYear = year;
                startTime.dwMonth = month;
                startTime.dwDay = day;
                startTime.dwHour = 0;
                startTime.dwMinute = 0;
                startTime.dwSecond = 0;
                //结束时间
                endTime.dwYear = year;
                endTime.dwMonth = month;
                endTime.dwDay = day;
                endTime.dwHour = 23;
                endTime.dwMinute = 59;
                endTime.dwSecond = 59;

                //获取通道号
                LinkedList<Integer> channelNumberList = hkVideoService.createDeviceTreeV40();
                for (Integer c : channelNumberList) {
                    //搜索文件
                    //List<FileInfoVo> list = hkVideoService.findFileV30(startTime, endTime, c);
                    List<FileInfoVo> list = hkVideoService.findFileV40(startTime, endTime, c, 1);
                    if (!list.isEmpty()) {
                        //文件列表不为空
                        list.forEach(l -> {
                            String filePath = HKConfig.downloadPath + File.separator + l.getYyyyMMdd();
                            try {
                                File file = new File(filePath);
                                if (!file.exists()) {
                                    //创建文件夹
                                    file.mkdirs();
                                }
                                file = null;
                                filePath = filePath + File.separator + l.getDeviceId() + "-" + l.getHhmmss() + ".mp4";
                                File file1 = new File(filePath);
                                if (file1.exists()) {
                                    //删除文件
                                    file1.deleteOnExit();
                                }
                                //创建文件
                                file1.createNewFile();
                                file1 = null;
                            } catch (IOException e) {
                                e.printStackTrace();
                                return;
                            }
                            //根据文件名称来下载
                            logger.info("文件下载路径：{}", filePath);
                            NativeLong downLoad = hkSdk.NET_DVR_GetFileByName(nlUserID, l.getFileName(), filePath);
                            if (downLoad.intValue() >= 0) {
                                IntByReference intByRef = new IntByReference(0);
                                Pointer lpInBuffer = intByRef.getPointer();
                                //发送下载指令
                                boolean b = hkSdk.NET_DVR_PlayBackControl_V40(downLoad, HCNetSDK.NET_DVR_PLAYSTART, lpInBuffer, 4, null, null);
                                //boolean b = hkSdk.NET_DVR_PlayBackControl(m_lDownloadHandle, HCNetSDK.NET_DVR_PLAYSTART, 0, null);
                                if (!b) {
                                    logger.info("下载播放错误码：{}", hkSdk.NET_DVR_GetLastError());
                                }
                                //创建定时器获取下载进度
                                /*timer = new Timer();
                                timer.schedule(new DownloadTask(filePath), 0, 1000);*/
                                Timer timer = new Timer(l.getFileName());
                                timer.schedule(new DownloadTask(filePath, timer, downLoad), 0, 1000);
                            } else {
                                logger.info("Download failed,error code: {}", hkSdk.NET_DVR_GetLastError());
                                return;
                            }
                        });
                    }
                }
            } else {
                hkSdk.NET_DVR_StopGetFile(m_lDownloadHandle);
                m_lDownloadHandle.setValue(-1);
                if (!Objects.equals(timer, null)) {
                    timer.cancel();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "下载测试";
    }

    /**
     * 下载定时器响应函数
     */
    class DownloadTask extends java.util.TimerTask {

        private volatile String filePath;

        private volatile Timer timer;

        private volatile NativeLong downLoad;

        public DownloadTask(String filePath, Timer timer, NativeLong downLoad) {
            this.filePath = filePath;
            this.timer = timer;
            this.downLoad = downLoad;
        }

        @Override
        public void run() {
            int iPos = hkSdk.NET_DVR_GetDownloadPos(downLoad);
            //logger.info("当前文件：{}", filePath);
            logger.info("下载进度：{}", iPos);
            if (iPos >= 100 || iPos < 0) {
                timer.cancel();
                hkSdk.NET_DVR_StopGetFile(downLoad);
                downLoad.setValue(-1);
            }
            if (iPos < 0) {
                // failed
                logger.info("下载进度错误码：{}", hkSdk.NET_DVR_GetLastError());
                logger.info("Get download progress failed,error code: {}", hkSdk.NET_DVR_GetLastError());
            }
            if (iPos == 100) {
                // end download
                logger.info("Downlaod ending 下载结束");
                logger.info("文件路径：{}", filePath);
            }
            if (iPos > 100) {
                // download exception for network problems or DVR
                logger.info("NetWork or DVR busing ,download exception stop");
                logger.info("网络或设备忙碌，下载异常停止");
            }
        }
    }


    /**
     * 启动监听
     *
     * @return
     */
    @PostMapping(value = "startMonitor")
    public String startMonitor() {
        init();
        System.out.println("监听启动");
        if (hkVideoMonitor == null) {
            hkVideoMonitor = new HkVideoMonitor();
        }
        Pointer pUser = null;
        //设置警报信息回调
        boolean b = hkSdk.NET_DVR_SetDVRMessageCallBack_V30(hkVideoMonitor, pUser);
        System.out.println("错误码：" + hkSdk.NET_DVR_GetLastError());
        if (!b) {
            System.out.println("设置回调函数失败!");
            return "设置回调函数失败";
        }
        System.out.println("设置回调函数成功!");
        //布防
        alarmChan = hkSdk.NET_DVR_SetupAlarmChan_V30(nlUserID);
        if (alarmChan.longValue() == -1) {
            System.out.println("错误码：" + hkSdk.NET_DVR_GetLastError());
            System.out.println("布防失败");
        }
        System.out.println("布防成功");

        //本地IP地址置为null时自动获取本地IP
        lListenHandle = hkSdk.NET_DVR_StartListen_V30(null, (short) 9211, hkVideoMonitor, null);
        if (lListenHandle.intValue() == -1) {
            System.out.println("错误码：" + hkSdk.NET_DVR_GetLastError());
            System.out.println("开始监听失败");
            return "开始监听失败";
        }
        System.out.println("开始监听。。。。");
        return "开始监听。。。。";
    }

    /**
     * 停止监听
     *
     * @return
     */
    @PostMapping(value = "stopMonitor")
    public String stopMonitor() {
        if (Objects.equals(lListenHandle, null)) {
            return "未开启监听";
        }
        //停止监听
        if (lListenHandle.intValue() != -1) {
            if (!hkSdk.NET_DVR_StopListen_V30(lListenHandle)) {
                System.out.println("停止监听失败");
                lListenHandle = new NativeLong(-1);
            } else {
                System.out.println("停止监听成功");
                lListenHandle = new NativeLong(-1);
            }
        }
        if (!Objects.equals(alarmChan, null)) {
            boolean b = hkSdk.NET_DVR_CloseAlarmChan_V30(alarmChan);
            if (!b) {
                System.out.println("停止布防失败");
                alarmChan = new NativeLong(-1);
            } else {
                System.out.println("停止布防成功");
                alarmChan = new NativeLong(-1);
            }
        }
        return "停止监听";
    }

}
